#!/bin/sh
#
# Copyright (C) 2000-2025 Kern Sibbald
# License: BSD 2-Clause; see file LICENSE-FOSS
#
# Test for the 'o' accurate backup (virtual full variant) option to backup only file's metadata
# if file contets did not change.
#

TestName="accurate-only-meta-virtual-full-test"
JobName=backup
. scripts/functions
$rscripts/cleanup

scripts/copy-migration-confs

change_jobname NightlySave $JobName

rm -f ${cwd}/build/testfile

# Turn accurate mode on for Job
$bperl -e "add_attribute('$conf/bacula-dir.conf', 'Accurate', 'Yes', 'Job', 'backup')"

cat <<END_OF_DATA >>${conf}/bacula-dir.conf
FileSet {
 Name = FS_META_TEST
 Include {
    Options {
      Signature = MD5
      Verify = mc
      Accurate = c5o
    }
    File=<${cwd}/tmp/file-list
 }
}
END_OF_DATA

$bperl -e 'add_attribute("$conf/bacula-dir.conf", "FileSet", "FS_META_TEST" , "Job", "backup")'

echo "${cwd}/build" >${cwd}/tmp/file-list
# Add one more file
dd if=/dev/urandom of=${cwd}/build/testfile count=10 bs=1M

start_test

# Run normal backup
cat <<END_OF_DATA >${cwd}/tmp/bconcmds
@$out /dev/null
messages
label volume=TestVolume001 storage=File pool=Default
label storage=DiskChanger volume=ChangerVolume001 slot=1 Pool=Full drive=0
label storage=DiskChanger volume=ChangerVolume002 slot=2 Pool=Full drive=0
messages
@$out ${cwd}/tmp/log1.out
run job=$JobName yes
wait
messages
quit
END_OF_DATA

run_bacula

# Sleep for a few seconds, touch all files to change each file's metadata
sleep 3
files_count=`find ${cwd}/build -type f | wc -l`
find ${cwd}/build -type f -exec touch {} + > /dev/null
# Change some properties of testfile
chmod 740 ${cwd}/build/testfile

# Run backup for the second time, this time we expect that only metadata part for each file will be
# backed up, so we expect the backup size to be much smaller than the first one.
cat <<END_OF_DATA >${cwd}/tmp/bconcmds
@$out ${cwd}/tmp/log2.out
run job=$JobName level=Incremental yes
wait
messages
quit
END_OF_DATA

run_bconsole

# Change permissions once more
chmod 776 ${cwd}/build/testfile
perm_after=`stat -c %a ${cwd}/build/testfile`

cat <<END_OF_DATA >${cwd}/tmp/bconcmds
@$out ${cwd}/tmp/log3.out
run job=$JobName level=Differential yes
wait
messages
@$out ${cwd}/tmp/log4.out
run job=$JobName level=VirtualFull yes
wait
messages
@$out ${cwd}/tmp/log5.out
restore select all done yes
wait
messages
quit
END_OF_DATA

run_bconsole

# Check if number of second backup files equals to files touched
backup_files=`cat ${cwd}/tmp/log2.out | grep 'FD Files Written:' | tr -s ' ' | cut -d ':' -f 2 | sed s/,//`
if [ ${backup_files} -ne ${files_count} ]; then
   estat=1
   print_debug "Wrong number of files backed up: ${backup_files}, expected: ${files_count}"
fi

# Check if testfile's restored from Vfull permission are correctly changed
perm_restored=`stat -c %a ${cwd}/tmp/bacula-restores/${cwd}/build/testfile`
if [ ${perm_after} -ne ${perm_restored} ]; then
   estat=1
   print_debug "Wrong permissions restored: ${perm_restored}, expected: ${perm_after}"
fi

# Make sure that second (incremental) and third (differential) backup was only some KB so that only metadata is transferred
bytes_written_kb=`cat tmp/log2.out | grep 'SD Bytes Written' | grep '(.* KB)' | wc -l`
if [ ${bytes_written_kb} -ne 1 ]; then
   estat=1
   print_debug "SD Bytes Written not expressed in KB as expected!"
fi

bytes_written_kb=`cat tmp/log3.out | grep 'SD Bytes Written' | grep '(.* KB)' | wc -l`
if [ ${bytes_written_kb} -ne 1 ]; then
   estat=1
   print_debug "SD Bytes Written not expressed in KB as expected!"
fi

# For the virtual full we expect size to be expressed in MBs
bytes_written_kb=`cat tmp/log4.out | grep 'SD Bytes Written' | grep '(.* MB)' | wc -l`
if [ ${bytes_written_kb} -ne 1 ]; then
   estat=1
   print_debug "SD Bytes Written not expressed in KB as expected!"
fi

$rscripts/diff.pl -s $cwd/build -d $tmp/bacula-restores/$cwd/build
if [ $? -ne 0 ]; then
    print_debug "ERROR: Found difference after restore"
    rstat=1
fi

# Cleanup
rm ${cwd}/build/testfile

stop_bacula
end_test
